package com.leetcode.concurrency;

/**
 * @author Dennis Li
 * @date 2020/9/17 10:13
 */
public class DiningPhilosophers {

    // 用于标识左右的刀叉
    private final Object[] forks;
    // 用于进入临界区
    private final Object mutex;

    public DiningPhilosophers() {
        mutex = new Object();
        forks = new Object[5];
        for (int i = 0; i < 5; i++) {
            forks[i] = new Object();
        }
    }

    // call the run() method of any runnable to execute its code
    public void wantsToEat(int philosopher,
                           Runnable pickLeftFork,
                           Runnable pickRightFork,
                           Runnable eat,
                           Runnable putLeftFork,
                           Runnable putRightFork) throws InterruptedException {
        // 一次只能让一个哲学家进入临界区
        synchronized (mutex) {
            // 当有其他哲学
            synchronized (forks[philosopher]) {
                synchronized (forks[(philosopher + 1) % 5]) {
                    pickLeftFork.run();
                    pickRightFork.run();
                    eat.run();
                    putLeftFork.run();
                    putRightFork.run();
                }
            }
        }
    }
}
